#ifndef _AI_VEHICLE_
#define _AI_VEHICLE_

#pragma once

#include "Puppet.h"
#include "CAISystem.h"


class CAIVehicle : public CPuppet
{
public:
	CAIVehicle();

	virtual void Update(EObjectUpdate type);
	virtual void UpdateDisabled(EObjectUpdate type);
	virtual void Event(unsigned short eType, SAIEVENT* pAIEvent);
	virtual void Reset(EObjectResetType type);
	virtual void ParseParameters(const AIObjectParams& params, bool bParseMovementParams = true);
	virtual void Serialize(TSerialize ser);
	virtual EntityId GetPerceivedEntityID() const;
	virtual bool IsTargetable() const { return IsActive(); }
	virtual bool IsActive() const { return m_bEnabled || IsDriverInside(); }

	void Navigate(CAIObject* pTarget);
	void AlertPuppets();
	bool HandleVerticalMovement( const Vec3& targetPos );

	bool IsDriverInside() const;
	bool IsPlayerInside();

	CAIActor* GetDriver() const;


protected:
	virtual void FireCommand();
	
	bool NoActorsInRadius2(short int objectType, Vec3& hitPosition, float fDamageRadius2, CAIObject** pTarget);


private:
	enum EDriverInsideCheckResult
	{
		eDICR_NotChecked,
		eDICR_Inside,
		eDICR_Outside,
	};

	EntityId GetDriverEntityId() const;
	void SetDriverInside(bool bInside);

	// Helper functions for FireCommand()
	Vec3 PredictMovingTarget(const CAIObject* pTarget, const Vec3& vTargetPos, const Vec3& vFirePos, const float duration, const float distpred);
	bool CheckExplosion(const Vec3& vTargetPos, const Vec3& vFirePos, const Vec3& vActualFireDir, const float fDamageRadius);
	Vec3 GetError(const Vec3& vTargetPos, const Vec3& vFirePos, const float fAccuracy);

	CTimeValue m_fFiringStartTime;			// The time the FireCommand started
	CTimeValue m_fFiringPauseTime;			// Pause time after the turret rotation has completed
	CTimeValue m_fNextFiringTime;				// The time of the next firing.

	Vec3		m_vDeltaTarget;				// Delta to the target position to provide for errors and movement prediction

	int			m_ShootPhase;
	mutable int m_eDriverInsideCheckResult;
	int			m_ePlayerInsideCheckResult;
	bool		m_bDriverInside;
	bool		m_bPoweredUp;
};

ILINE const CAIVehicle* CastToCAIVehicleSafe(const IAIObject* pAI) { return pAI ? pAI->CastToCAIVehicle() : 0; }
ILINE CAIVehicle* CastToCAIVehicleSafe(IAIObject* pAI) { return pAI ? pAI->CastToCAIVehicle() : 0; }

#endif	// #ifndef _AI_VEHICLE_
